<template>
  <div ref="chartContainer" class="d3-chart pos-relative"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch } from "vue";
import * as d3 from "d3";

const props = defineProps({
  data: {
    type: Array as () => number[],
    required: true,
  },
  tooltip: {
    type: Boolean,
    default: true,
  },
  highlightColor: {
    type: String,
    default: "#cccccc67",
  },
  showGrid: {
    type: Boolean,
    default: true,
  },
  gridColor: {
    type: String,
    default: "#eee",
  },
  // 移除固定的 width/height，改为从父元素获取
  margin: {
    type: Object as () => { top: number; right: number; bottom: number; left: number },
    default: () => ({ top: 20, right: 20, bottom: 30, left: 40 }),
  },
});

const chartContainer = ref<HTMLElement | null>(null);
const width = ref(0);
const height = ref(0);
const offsetX = ref<number>(0);
const offsetY = ref<number>(0);
let observer: ResizeObserver | null = null;

// 计算实际绘图区域
const innerWidth = () => width.value - props.margin.left - props.margin.right;
const innerHeight = () => height.value - props.margin.top - props.margin.bottom;

function renderChart() {
  if (!chartContainer.value || !props.data.length || width.value === 0) return;

  // 清除旧图表
  d3.select(chartContainer.value).selectAll("*").remove();

  // 创建SVG
  const svg = d3
    .select(chartContainer.value)
    .append("svg")
    .attr("width", width.value)
    .attr("height", height.value);

  // 创建绘图区域
  const g = svg
    .append("g")
    .attr("transform", `translate(${props.margin.left}, ${props.margin.top})`);
  // 创建工具提示元素
  const tooltip = d3
    .select(chartContainer.value)
    .append("div")
    .attr("class", "tooltip")
    .style("opacity", 0)
    .style("position", "absolute")
    .style("background", "white")
    .style("border", "1px solid #ddd")
    .style("border-radius", "4px")
    .style("padding", "8px")
    .style("pointer-events", "none")
    .style("font-size", "12px")
    .style("box-shadow", "0 2px 4px rgba(0,0,0,0.2)");

  // 创建悬停背景矩形组
  const hoverBackgroundGroup = g.append("g").attr("class", "hover-background");
  // 比例尺（使用实际绘图区域尺寸）
  const xScale = d3
    .scaleBand()
    .domain(props.data.map((_, i) => i.toString()))
    .range([0, innerWidth()])
    .padding(0.62);

  const yScale = d3
    .scaleLinear()
    .domain([0, d3.max(props.data) || 100])
    .range([innerHeight(), 0]);

  // 添加水平网格线
  if (props.showGrid) {
    g.append("g")
      .attr("class", "grid")
      .call(
        d3
          .axisLeft(yScale)
          .tickSize(-innerWidth())
          .tickFormat(() => "")
      )
      .selectAll("line")
      .attr("stroke", props.gridColor)
      .attr("stroke-opacity", 0.25)
      .attr("stroke-dasharray", "2,2");
  }

  // 添加垂直网格线
  if (props.showGrid) {
    g.append("g")
      .attr("class", "grid")
      .attr("transform", `translate(0, ${innerHeight()})`)
      .call(
        d3
          .axisBottom(xScale)
          .tickSize(-innerHeight())
          .tickFormat(() => "")
      )
      .selectAll("line")
      .attr("stroke", props.gridColor)
      .attr("stroke-opacity", 0.3)
      .attr("stroke-dasharray", "2,2");
  }
  // 绘制柱状图
  const bars = g
    .selectAll("rect")
    .data(props.data)
    .enter()
    .append("rect")
    .attr("rx", 5) // 圆角半径
    .attr("ry", 5)
    .attr("x", (_d, i) => xScale(i.toString()) || 0)
    .attr("y", (d) => yScale(d))
    .attr("width", xScale.bandwidth())
    .attr("height", (d) => innerHeight() - yScale(d))
    .attr("fill", "#02bff8")
    .style("cursor", "pointer"); // 这里添加鼠标指针样式;
  // 添加鼠标悬停效果
  if (props.tooltip) {
    bars
      .on("mouseover", function (event, d) {
        const [_x, _y] = d3.pointer(event, svg.node());
        const index = props.data.indexOf(d);
        d3.select(this).attr("fill", "#0077b6"); // 悬停时改变颜色
        // 添加悬停背景
        hoverBackgroundGroup
          .append("rect")
          .attr("class", "highlight-background")
          .attr("x", (xScale(index.toString()) || 0) - 10)
          .attr("y", 0)
          .attr("width", xScale.bandwidth() + 20)
          .attr("height", innerHeight())
          .attr("fill", props.highlightColor)
          .attr("rx", 0)
          .attr("ry", 0);
        tooltip.transition().duration(200).style("opacity", 0.9);
        tooltip
          .html(`值: ${d}`)
          .style("color", "#fff")
          .style("border", "0px none")
          .style("background-color", "rgba(0, 0, 0, 0.58)")
          .style("left", `${event.pageX - offsetX.value  + 10}px`)
          .style("top", `${event.pageY - offsetX.value - 28}px`);
      })
      .on("mouseout", function () {
        d3.select(this).attr("fill", "#02bff8"); // 恢复原颜色
        // 移除悬停背景
        hoverBackgroundGroup.selectAll(".highlight-background").remove();
        // 隐藏工具提示
        tooltip.transition().duration(500).style("opacity", 0);
      });
  }
  // 添加x轴（底部轴）
  const xAxis = g
    .append("g")
    .attr("class", "x-axis")
    .attr("transform", `translate(0, ${innerHeight()})`)
    .call(d3.axisBottom(xScale));

  // 移除x轴的顶部边框线
  xAxis.select(".domain").remove();

  // 添加y轴（左侧轴）
  g.append("g")
    .attr("class", "y-axis") // 添加类名以便样式控制
    .call(d3.axisLeft(yScale))
    // 移除顶部和右侧的边框线
    .select(".domain")
    .attr("stroke", "none");
}

// 监听容器尺寸变化
const initResizeObserver = () => {
  if (!chartContainer.value) return;

  observer = new ResizeObserver((entries) => {
    const entry = entries[0];
    width.value = entry.contentRect.width;
    height.value = entry.contentRect.height;
    renderChart();
  });
  observer.observe(chartContainer.value);
};

// 初始化
onMounted(() => {
  offsetX.value = chartContainer.value?.getBoundingClientRect().left as number;
  offsetY.value = chartContainer.value?.getBoundingClientRect().top as number;
  initResizeObserver();
});

// 清理
onBeforeUnmount(() => {
  observer?.disconnect();
});

// 响应数据变化
watch(() => props.data, renderChart);
</script>

<style scoped>
.d3-chart {
  width: 100%; /* 确保充满父容器 */
  height: 100%; /* 或指定具体高度，如 400px */
  min-height: 200px; /* 建议设置最小高度 */
  resize: both; /* 可选：允许用户手动调整大小 */
  overflow: hidden; /* 防止内容溢出 */
}
/* 确保所有坐标轴的边框都被移除 */
.d3-chart :deep(.domain) {
  display: none;
  stroke: none;
}

/* 如果需要，可以单独控制x轴和y轴的样式 */
.d3-chart :deep(.x-axis path),
.d3-chart :deep(.x-axis line) {
  stroke: #000; /* 保留x轴的底部线和刻度线 */
}

.d3-chart :deep(.y-axis path),
.d3-chart :deep(.y-axis line) {
  stroke: #000; /* 保留y轴的左侧线和刻度线 */
}
/* 工具提示样式 */
.tooltip {
  position: absolute;
  border-radius: 4px;
  padding: 8px;
  pointer-events: none;
  font-size: 12px;
  z-index: 10;
}

/* 悬停背景样式 */
.highlight-background {
  transition: opacity 0.2s ease;
}
</style>
